// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using System.Linq;
using NUnit.Framework;
using ValidationAspects;
using ValidationAspects.Core;
using ValidationAspects.Sdk;

namespace TestValidationAspects.Core
{
	[TestFixture]
	public class TestCompoundValidatorFactory
	{
		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_Constructor_throws_for_null_param()
		{
			new CompoundValidatorFactory(null);
		}

		[Test]
		public void Test_Create_returns_a_validator_which_calls_the_supplied_validators()
		{
			MockValidatorFactory<object>[] factories = new[] {new MockValidatorFactory<object>(), new MockValidatorFactory<object>(),};
			CompoundValidatorFactory factory = new CompoundValidatorFactory(factories);

			IValidator<object> validator = factory.Create<object>();

			Assert.IsNull(factories.Select(f => f.Validator).FirstOrDefault(v => v.Value != null));

			object value = new object();
			IValidationContext context = new MockValidationContext();
			validator.Invoke(value, context);

			Assert.IsNull(factories.Select(f => f.Validator).FirstOrDefault(v => v.Value != value && v.Context != context));
		}

		#region Mocks
		public class MockValidator<T> : IValidator<T>
		{
			public T Value { get; set; }
			public IValidationContext Context { get; set; }

			#region Implementation of IValidator
			public void Invoke(T value, IValidationContext context)
			{
				Value = value;
				Context = context;
			}

			public void Invoke(object value, IValidationContext context)
			{
				Value = (T)value;
				Context = context;
			}
			#endregion
		}

		public class MockValidatorFactory<TValue> : IValidatorFactory
		{
			public MockValidator<TValue> Validator { get; set; }

			#region Implementation of IValidatorFactory
			public IValidator<T> Create<T>()
			{
				Validator = new MockValidator<TValue>();
				return Adapt<T, TValue>.From(Validator);
			}
			#endregion
		}
		#endregion
	}
}